home *** CD-ROM | disk | FTP | other *** search
- /* ICMP-related user commands */
- #include <stdio.h>
- #include "global.h"
- #include "icmp.h"
- #include "mbuf.h"
- #include "netuser.h"
- #include "internet.h"
- #include "timer.h"
- #include "socket.h"
- #include "proc.h"
- #include "session.h"
-
- extern struct icmp_errors Icmp_errors;
- extern struct icmp_stats Icmp_stats;
- extern int32 Clock;
- extern char *Icmptypes[];
- char *inet_ntoa();
- struct mbuf *htonicmp();
- void pingtx();
- static int pingem();
-
- int
- doicmpstat()
- {
- register int i;
-
- printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
- Icmp_errors.checksum,Icmp_errors.nospace,Icmp_errors.noloop,
- Icmp_errors.bdcsts);
- printf("type rcvd sent\n");
- for(i=0;i<ICMP_TYPES;i++){
- if(Icmp_stats.input[i] == 0 && Icmp_stats.output[i] == 0)
- continue;
- printf("%-6u%-6u%-6u",i,Icmp_stats.input[i],
- Icmp_stats.output[i]);
- if(Icmptypes[i] != NULLCHAR)
- printf(" %s",Icmptypes[i]);
- printf("\n");
- }
- return 0;
- }
-
- /* Send ICMP Echo Request packets */
- doping(argc,argv)
- int argc;
- char *argv[];
- {
- struct proc *pinger = NULLPROC; /* Transmit process */
- struct sockaddr_in to,from;
- struct icmp icmp;
- struct mbuf *bp;
- struct session *sp;
- int32 timestamp,rtt,abserr;
- int s,fromlen;
- struct ping ping;
-
- memset((char *)&ping,0,sizeof(ping));
- /* Allocate a session descriptor */
- if((sp = newsession(argv[1],PING)) == NULLSESSION){
- printf("Too many sessions\n");
- return 1;
- }
- sp->cb.ping = &ping;
- ping.sp = sp;
-
- ping.proc = Curproc;
- if((sp->s = s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1){
- printf("Can't create socket\n");
- freesession(sp);
- return 1;
- }
- Current = sp;
- Mode = CONV_MODE;
- to.sin_family = AF_INET;
- if((to.sin_addr.s_addr = resolve(argv[1])) == 0){
- printf("Host %s unknown\n",argv[1]);
- close_s(s);
- freesession(sp);
- return 1;
- }
- connect(s,(char *)&to,sizeof(to));
-
- if(argc > 2)
- ping.len = atoi(argv[2]);
-
- if(argc > 3)
- ping.interval = atoi(argv[3]);
-
- if(ping.interval != 0){
- pinger = newproc("pingtx",300,pingtx,s,&ping,NULL);
- } else {
- ping.sent = 1;
- pingem(s,0,(int16)Curproc,ping.len);
- }
- /* Now collect the replies */
- for(;;){
- fromlen = sizeof(from);
- if(recv_mbuf(s,&bp,0,0,(char *)&from,&fromlen) == -1)
- break;
- ntohicmp(&icmp,&bp);
- if(icmp.type != ECHO_REPLY
- || from.sin_addr.s_addr != to.sin_addr.s_addr
- || icmp.args.echo.id != (int16)Curproc){
- /* Ignore other people's responses */
- free_p(bp);
- continue;
- }
- ping.responses++;
- pullup(&bp,(char *)×tamp,sizeof(Clock)); /* Get stamp */
- free_p(bp);
-
- /* Compute round trip time, update smoothed estimates */
- rtt = (Clock - timestamp) * MSPTICK;
- if(ping.interval == 0){
- printf("%s: rtt %lu",sp->name,rtt);
- break;
- }
- abserr = rtt > ping.srtt ? rtt - ping.srtt : ping.srtt - rtt;
- if(ping.responses == 1){
- /* First response, base entire SRTT on it */
- ping.srtt = rtt;
- } else {
- ping.srtt = (7*ping.srtt + rtt + 4) >> 3;
- }
- ping.mdev = (3*ping.mdev + abserr + 2) >> 2;
-
- }
- if(Current == sp && Mode == CONV_MODE)
- printf("\n");
- if(pinger != NULLPROC)
- killproc(pinger);
- close_s(s);
- freesession(sp);
- return 0;
- }
- /* Ping transmit process. Runs until killed */
- void
- pingtx(s,ping)
- int s; /* Socket to use */
- struct ping *ping;
- {
- long sdur;
-
- sdur = ping->interval * (1000 / MSPTICK);
- ping->sent = 0;
- for(;;){
- if(Current == ping->sp && Mode == CONV_MODE){
- printf("pinging %s: sent %lu rcvd %lu avg rtt %lu mdev %lu \r",
- ping->sp->name,ping->sent,ping->responses,ping->srtt,
- ping->mdev);
- }
- pingem(s,(int16)ping->sent++,(int16)ping->proc,ping->len);
- pause(sdur);
- }
- }
-
-
- /* Send ICMP Echo Request packet */
- static
- pingem(s,seq,id,len)
- int s; /* Raw socket on which to send ping */
- int16 seq; /* ICMP Echo Request sequence number */
- int16 id; /* ICMP Echo Request ID */
- int16 len; /* Length of optional data field */
- {
- struct mbuf *data = NULLBUF;
- struct mbuf *bp;
- struct icmp icmp;
-
- if((data = alloc_mbuf(len+sizeof(Clock))) == NULLBUF)
- return -1;
- data->cnt = len+sizeof(Clock);
- /* Set optional data field, if any, to all 1's */
- if(len != 0)
- memset(data->data+sizeof(Clock),0xff,len);
-
- /* Insert timestamp and build ICMP header */
- memcpy(data->data,(char *)&Clock,sizeof(Clock));
- Icmp_stats.output[ECHO]++;
- icmp.type = ECHO;
- icmp.code = 0;
- icmp.args.echo.seq = seq;
- icmp.args.echo.id = id;
- if((bp = htonicmp(&icmp,data)) == NULLBUF){
- free_p(data);
- return 0;
- }
- send_mbuf(s,bp,0,NULLCHAR,0);
- return 0;
- }
-
-
-